iT邦幫忙

2023 iThome 鐵人賽

DAY 24
0
Cloud Native

2023 年了,一起來學 CDN - 你也可以瞭解的 CloudFront 系列 第 24

Day 24 - 透過 CloudFront 保護內容不被盜用。

  • 分享至 

  • xImage
  •  

無論有無使用 CloudFront,內容的保護常是提供網站內容的人想要瞭解/達成的目標。
比方說,希望對應的 link 僅在特定時間範圍內有效,才能下載。
有一個方法,是由 CloudFront 提供,可以適用這樣的情境,也是我們今天要介紹的功能,「Signed URL」

概念上,SingedURL 是這樣運作的:

1. 首先你要有一組加密的 Key,其中Private Key 自己保留,Public Key 上傳到 CloudFront 之中。
2. 使用這把 Private Key 加密你要保護的 URL,然後將加密後的字串以 QueryString 的方式附加在原本的 URL 之後。
3. 指定 CloudFront 的對應 Behavior,讓 CloudFront在處理特定 URL Prefix 時需要先嘗試解開你以 Private Key 加密的QueryString 字串,確認相關網址沒被竄改 or 冒用。
4. 如果沒被竄改/冒用--> Let go,繼續後續處理。如果發現加密的字串解不開 or被竄改/冒用了--> 阻攔下來(403)
5. 對了,如果可以放行,相關的回覆內容也可以緩存在 CloudFront 中。

坐著看不如捲起袖子動手,一起來試試吧。以下是一個範例作法。

首先我們要有一個可以使用的網址,我們就用這個吧:
要透過 SingedURL 才能存取的網址: https://dqofozeouve3j.cloudfront.net/0m-HR.mp4
同樣內容,做為參考用: https://dqofozeouve3j.cloudfront.net/static_files/0m-HR.mp4

以下是相關步驟,測試環境是 MacOS,你需要安裝 openssl & perl (這兩個應該內建都有)

  1. 準備加密的 Public Key,我們可以透過 openssl 指令建立 public & private key.
$ openssl genrsa -out private_key.pem 2048
  1. 取出剛建立好的key 內的 public key
$ openssl rsa -pubout -in private_key.pem -out public_key.pem
  1. 這時候對應的工作路徑下應該會有兩個 .pem
$ ls -l p*.pem
-rw-r--r--  1 kgg23  staff  1679 Sep 26 23:20 private_key.pem
-rw-r--r--  1 kgg23  staff   451 Sep 26 23:20 public_key.pem
  1. 這時切換到 CloudFront Console,左側選單選 'Public Keys',點 Create 創立一組新的 Key,並取個名字,比方說 ironman2023-public-key
    將前面產出的 public_key.pem 的內容貼到下方的 public_key input text 去。按下創建 key
    https://ithelp.ithome.com.tw/upload/images/20230926/20162502OKqR9KWeFn.png

  2. 創建之後,記下這組 public-key 的 key-id(在 SignedURL 中就是 Key-Pair-Id),然後左側選單選到 key-group 去,創建一組Key group
    https://ithelp.ithome.com.tw/upload/images/20230926/20162502plyI3VwozF.png

  3. 創建一組新的 behavior,URL Path 對應剛的影片檔案,我們設定為 /0m-HR.mp4,要設置 CloudFront 限制存取(Restric Access),並設定其它的 Cache Behavior (ex: 緩存要存多久,要轉發哪些標頭等)
    https://ithelp.ithome.com.tw/upload/images/20230926/20162502LxGuG9S17S.png

  4. 準備一個 Policy 檔案,我們取名叫做 canned-policy,其內容如下。這是一個範例的 Policy,針對對應的URL網址,只要存取時間還沒超過 unix time: 1704038400 (2024.01.01 00:00:00),就可以存取。
    (注意 resource 名稱要正確,不然無法存取)

{
  "Statement":[
    { 
      "Resource":"https://dqofozeouve3j.cloudfront.net/0m-HR.mp4",
      "Condition":{
        "DateLessThan":{ "AWS:EpochTime":1704038400 }
        }
    }
  ]
}
  1. 用以下指令算出 URL,這是透過ssl 計算 signature,同時置換取代掉 '+','/', '=' 等不能使用的字元的結果。
$ cat canned-policy | tr -d " \t\n\r" | openssl sha1 -sign private_key.pem | openssl base64 | tr -- '+=/' '-_~' | tr -d "\n" | perl -ne 'print "$_\n"'

此時會得到一個字串類似如下,這就是我們的 Signature 值

MgC3QpYzOIPexUKQ1CSW2AOz7KpRnuqkR3F7xBub7L3QrMi1wGES-eXN2tfAPGbvT1HnKSbDE83IqRnaW32HGH-bG7y~wNWyLBrhBiVWRw~6Mw60uaz23MK5RRl8XSlBw0vZc9WDbcSKNimCjmzgJLH8j1Gc4N8KHmvt6xQsV2FXLJeScNGNJp3U-DAVcPCLZEmLzslz0BStTIQRX38YA4RBwGASiaLqGTHltJkELiMx4Qbf~XfWhO70tgESVL0WxNS6jzcpyUYXvGfKEW07aYZbzMmbZwghO1U2Ur9hmRCyy~FdNFpN5pGiMnUIHkM4SJwGcVBi7EnTJUbIA2UKdA__
  1. 這時候,把相關的參數組合起來:
    也就是說,將你的網址後加上 Expires, Signature & Key-Pair-Id 等 3個數值。

https://dqofozeouve3j.cloudfront.net/0m-HR.mp4?Expires=1704038400&Signature=MgC3QpYzOIPexUKQ1CSW2AOz7KpRnuqkR3F7xBub7L3QrMi1wGES-eXN2tfAPGbvT1HnKSbDE83IqRnaW32HGH-bG7y~wNWyLBrhBiVWRw~6Mw60uaz23MK5RRl8XSlBw0vZc9WDbcSKNimCjmzgJLH8j1Gc4N8KHmvt6xQsV2FXLJeScNGNJp3U-DAVcPCLZEmLzslz0BStTIQRX38YA4RBwGASiaLqGTHltJkELiMx4Qbf~XfWhO70tgESVL0WxNS6jzcpyUYXvGfKEW07aYZbzMmbZwghO1U2Ur9hmRCyy~FdNFpN5pGiMnUIHkM4SJwGcVBi7EnTJUbIA2UKdA__&Key-Pair-Id=KADKFBQ2AMLYW

完成啦!!
https://ithelp.ithome.com.tw/upload/images/20230927/201625023HgLAV74R6.png

使用 curl 驗證也 200 OK!

$ curl -vo /dev/null "https://dqofozeouve3j.cloudfront.net/0m-HR.mp4?Expires=1704038400&Signature=MgC3QpYzOIPexUKQ1CSW2AOz7KpRnuqkR3F7xBub7L3QrMi1wGES-eXN2tfAPGbvT1HnKSbDE83IqRnaW32HGH-bG7y~wNWyLBrhBiVWRw~6Mw60uaz23MK5RRl8XSlBw0vZc9WDbcSKNimCjmzgJLH8j1Gc4N8KHmvt6xQsV2FXLJeScNGNJp3U-DAVcPCLZEmLzslz0BStTIQRX38YA4RBwGASiaLqGTHltJkELiMx4Qbf~XfWhO70tgESVL0WxNS6jzcpyUYXvGfKEW07aYZbzMmbZwghO1U2Ur9hmRCyy~FdNFpN5pGiMnUIHkM4SJwGcVBi7EnTJUbIA2UKdA__&Key-Pair-Id=KADKFBQ2AMLYW"

< HTTP/2 200
< content-type: video/mp4
< content-length: 3616274
< date: Tue, 26 Sep 2023 16:04:50 GMT
< last-modified: Tue, 26 Sep 2023 15:06:20 GMT
< etag: "92574d268be41dde3e65ef4c89306ee1"
< x-amz-server-side-encryption: AES256
< accept-ranges: bytes
< server: AmazonS3
< x-cache: Miss from cloudfront
< via: 1.1 f0c65fa94f0c649f469c108c60821432.cloudfront.net (CloudFront)
< x-amz-cf-pop: TPE52-C1
< x-amz-cf-id: omyEWn1-QV_YB3Wae7vnDZegASCfTYkPNugnZI7saQWdixDgDi9pvw==

p.s. 此時直接存取沒帶 signature 等參數的 url時,會直接報 403.
ex: https://dqofozeouve3j.cloudfront.net/0m-HR.mp4

終於,我 們 完 成 啦!!


上一篇
Day 23 - CloudFront 的相關 Report & Metrics
下一篇
Day 25 - 與 AWS 服務整合 - Origin 篇(Part 1)
系列文
2023 年了,一起來學 CDN - 你也可以瞭解的 CloudFront 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言